package com.hw.protocol.tool.decode;

import com.hw.protocol.tool.config.DecodeContext;
import com.hw.protocol.tool.model.Result;
import com.hw.protocol.tool.model.entity.HbProtocol;
import com.hw.protocol.tool.util.CrcUtil;
import com.hw.protocol.tool.util.CryptoUtil;
import io.netty.buffer.ByteBuf;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * @author : lihy
 * @date : 2024/3/14 15:27
 * description:
 */
@Slf4j
@Component
public class HbDecode implements IDecode {

    @Override
    public Result decode(byte[] bytes) {
        ByteBuf in = wrapBytes(bytes);
        byte fh = in.getByte(0);
        if (fh != (byte) 0x68) {
            in.release();
            return Result.error("帧头错误");
        }
        HbProtocol pro = new HbProtocol();
        pro.setVersion(in.getByte(1));
        pro.setType(in.getByte(2));
        byte[] devSerialBytes = new byte[8];
        in.getBytes(3, devSerialBytes);
        //去除开头的0
        pro.setDevSerial(CrcUtil.bytesToHex(devSerialBytes).replaceFirst("^0+", ""));
        pro.setKey(in.getByte(11));
        pro.setCmd(in.getByte(12));
        pro.setObjId(in.getShortLE(13));
        short length = in.getShortLE(15);
        pro.setLength(length);

        byte[] noCrc = new byte[length + 14 + 2];
        in.getBytes(1, noCrc);
        //CRC
        byte[] crcBytes = new byte[2];
        in.getBytes(length + 15 + 2, crcBytes);
        pro.setCrc(crcBytes);

        pro.setEnd(in.getByte(length + 15 + 2 + 2));


        byte[] allBts = new byte[length + 15 + 2 + 2 + 1];
        in.getBytes(0, allBts);

        //crc验证
        if (!CrcUtil.checkCrc(noCrc, true, crcBytes)) {
            in.release();
            return Result.error("crc验证错误");
        }

        //原始数据
        byte[] originalDataBytes = new byte[length];
        in.getBytes(17, originalDataBytes);
        log.debug("原始数据：[{}]", CrcUtil.bytesToHex(originalDataBytes, true));
        if (pro.getKey() == 0) {
            //未加密
            pro.setData(CryptoUtil.stripPadding(originalDataBytes));
        } else {
            //根据key解密
            try {
                byte[] secret = CrcUtil.convert16HexToByte(DecodeContext.key.replace(" ", ""));
                log.debug("加密密钥：[{}]", CrcUtil.bytesToHex(secret, true));
                byte[] realData = CryptoUtil.decrypt(originalDataBytes, secret);
                log.debug("解密后数据：[{}]", CrcUtil.bytesToHex(realData, true));
                byte[] dataNoCrcData = Arrays.copyOfRange(realData, 0, realData.length - 2);
                byte[] dataCrc = Arrays.copyOfRange(realData, realData.length - 2, realData.length);
                if (!CrcUtil.checkCrc(dataNoCrcData, true, dataCrc)) {
                    in.release();
                    return Result.error("数据crc验证错误");
                }
                pro.setData(dataNoCrcData);
            } catch (Exception e) {
                log.error(e.getMessage(), e);
                return Result.error("数据解密失败");
            }
        }

        //释放ByteBuf
        in.release();

        return Result.success(pro);
    }
}
